Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

THandle.h

Go to the documentation of this file.
00001 ///////////////////////////////////////////////////////////////////////////////
00002 /// @file THANDLE.h
00003 ///
00004 /// @brief 
00005 ///
00006 /// @author trajar
00007 ///
00008 /// This file is the intellectual property of Novus Delta, LLC.. Usage of the
00009 /// contents of this file is subject to the Destiny3D Member License which
00010 /// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
00011 ///
00012 /// This file is distributed "AS IS" without warranty of any kind.  Novus
00013 /// Delta, LLC. does not guarantee the fitness of the contents of this file
00014 /// for any particular purpose.
00015 ///
00016 /// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
00017 ///
00018 /// <hr>
00019 ///                                 Change History
00020 /// <hr>
00021 ///
00022 /// @date Jun 2002
00023 /// @author trajar
00024 /// @remarks Creation
00025 ///
00026 ///////////////////////////////////////////////////////////////////////////////
00027 
00028 #ifndef _THANDLE_H
00029 #define _THANDLE_H
00030 
00031 #include    <assert.H>
00032 
00033 #ifndef     _VECTOR_
00034  #include   <vector>
00035 #endif
00036 
00037 #pragma warning( disable : 4786 )  
00038 #pragma warning( disable : 4285 )  
00039 
00040 #define  SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
00041 #define  SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
00042 #define  SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
00043 
00044 typedef unsigned long DWORD;
00045 
00046 enum EraseType
00047 {
00048     ERASE_UNKNOWN,
00049     ERASE_NORMAL,
00050     ERASE_DELETE,
00051     ERASE_DELETE_ARRAY,
00052     ERASE_RELEASE
00053 };
00054 
00055 //--------------------------------------------------
00056 // THandleMgr
00057 //--------------------------------------------------
00058 template <typename DATA, typename HANDLE>
00059 class THandleMgr
00060 {
00061 public:
00062 
00063     // public types
00064     typedef std::vector <DATA>              DataVec;
00065     typedef std::vector <unsigned int>      MagicVec;
00066     typedef std::vector <unsigned int>      FreeVec;
00067     typedef std::vector <int>               RefVec;
00068 
00069     // Lifetime.
00070 
00071     THandleMgr( void )   {  assert(!m_Singleton); 
00072                             m_Singleton = this; 
00073                             m_EraseType = ERASE_UNKNOWN; }
00074 
00075     ~THandleMgr( void )  { EraseEntries(); m_Singleton = NULL; }
00076 
00077     DATA *       GetDataAt(int Index)              { return (m_UserData.begin() + Index); } 
00078     void         SetEraseMethod( EraseType pType ) { assert(pType != ERASE_UNKNOWN); m_EraseType = pType; } 
00079     unsigned int GetUsedHandleCount( void ) const  {  return ( m_MagicNumbers.size() - m_FreeSlots.size() );  }    
00080     bool         HasUsedHandles( void ) const      {  return ( !!GetUsedHandleCount() );  }
00081     
00082     //-----------------------------------------------------------------
00083     // AddReference( HANDLE& )
00084     //
00085     // - adds a references to a handle
00086     // - returns the current reference count
00087     //-----------------------------------------------------------------
00088     int     AddReference( HANDLE& pHandle )
00089             {
00090                 if( !pHandle.IsNull() )
00091                 {                       
00092                     unsigned int index = pHandle.GetIndex();
00093                 
00094                     if( (index < m_UserData.size()) ||
00095                         (m_MagicNumbers[ index ] == pHandle.GetMagic()) )
00096                     {
00097                         int&     count = m_References[index];
00098                         return   count++;
00099                     }
00100                     else
00101                         return -1;
00102                 }
00103                 else
00104                     return -1;
00105             }
00106 
00107     //-----------------------------------------------------------------
00108     // ReleaseReference( HANDLE& )
00109     //
00110     // - releases a reference to a handle
00111     // - if no more references are found, the in release the handle
00112     // - returns the current reference count
00113     //-----------------------------------------------------------------
00114     int     ReleaseReference( HANDLE& pHandle )
00115             {
00116                 if( !pHandle.IsNull() )
00117                 {
00118                     unsigned int index = pHandle.GetIndex();
00119                              int& count = m_References[index];
00120                     
00121                      if(    (index < m_UserData.size()) ||
00122                          (m_MagicNumbers[ index ] == pHandle.GetMagic()) )
00123                      {
00124                         count--;
00125                         if( count == 0 )  // release it
00126                         {
00127                             Release(pHandle);
00128                             pHandle = HANDLE();
00129                             m_References[index] = -1;
00130                             return 0;
00131                         }
00132                         else
00133                             return count;
00134                      }
00135                      else
00136                          return -1;
00137                 }
00138                 else
00139                     return -1;
00140             }
00141 
00142     //-----------------------------------------------------------------
00143     // DATA * Acquire( HANDLE& )
00144     //
00145     // Adds/returns handle AND address of data
00146     //
00147     // * NOTE * if data is a ptr, changing it will not 
00148     //          change the data in this mgr
00149     //-----------------------------------------------------------------
00150     DATA*   Acquire( HANDLE& handle )
00151             {
00152                 assert( !handle.IsNull() );
00153 
00154                 // if free list is empty, add a new one otherwise use first one found
00155                 
00156                 unsigned int index;
00157                 if ( m_FreeSlots.empty() )
00158                 {
00159                     index = m_MagicNumbers.size();
00160                     handle.Init( index );
00161                     m_UserData.push_back( DATA() );
00162                     m_References.push_back(1);
00163                     m_MagicNumbers.push_back( handle.GetMagic() );
00164                 }
00165                 else
00166                 {
00167                     index = m_FreeSlots.back();
00168                     handle.Init( index );
00169                     m_References[ index ] = 1;
00170                     m_FreeSlots.pop_back();
00171                     m_MagicNumbers[ index ] = handle.GetMagic();
00172                 }
00173                 return ( m_UserData.begin() + index );
00174             }
00175 
00176     //-----------------------------------------------------------------
00177     // bool AddItem( HANDLE, const DATA )
00178     //
00179     // Adds a data item to the manager and returns the handle
00180     //      - returns true if successful
00181     //-----------------------------------------------------------------
00182     DATA *  AddItem( HANDLE& handle, const DATA& data )
00183             {
00184                 bool bOK = false;
00185                 // if free list is empty, add a new one otherwise use first one found
00186 
00187                 unsigned int index;
00188                 if ( m_FreeSlots.empty() )
00189                 {
00190                     index = m_MagicNumbers.size();
00191                     handle.Init( index );
00192                     m_UserData.push_back( data );
00193                     m_References.push_back(1);
00194                     m_MagicNumbers.push_back( handle.GetMagic() );
00195                     bOK = true;
00196                 }
00197                 else
00198                 {
00199                     index = m_FreeSlots.back();
00200                     handle.Init( index );
00201                     m_FreeSlots.pop_back();
00202                     m_References[ index ] = 1;
00203                     m_MagicNumbers[ index ] = handle.GetMagic();
00204                     m_UserData[ index ] = data;
00205                     bOK = true;
00206                 }
00207                                 
00208                 m_References[index] = 1;
00209 
00210                 return ( m_UserData.begin() + index );
00211             }
00212 
00213     //-----------------------------------------------------------------
00214     // Release( HANDLE  handle )
00215     //-----------------------------------------------------------------
00216     void    Release( HANDLE&  handle )
00217             {
00218                 // which one?
00219                 unsigned int index = handle.GetIndex();
00220 
00221                 if( handle.IsNull() )
00222                     return;
00223 
00224                 // make sure it's valid
00225                 if( (index < m_UserData.size()) ||
00226                     (m_MagicNumbers[ index ] == handle.GetMagic()) )
00227                 {
00228                     assert( m_EraseType != ERASE_UNKNOWN );
00229 
00230                     // clear up the numbers before we delete/release
00231                     m_MagicNumbers[ index ] = 0;
00232                     m_References[ index ] = -1;
00233                     m_FreeSlots.push_back( index );
00234                     handle = HANDLE();
00235 
00236                     // ok remove it - tag as unused and add to free list
00237                     switch( m_EraseType )
00238                     {
00239                     case ERASE_DELETE:
00240                         //SAFE_DELETE(m_UserData[index]);
00241                         assert(false);
00242                         break;
00243 
00244                     case ERASE_DELETE_ARRAY:
00245                         //SAFE_DELETE_ARRAY(m_UserData[index]);
00246                         assert(false);
00247                         break;
00248 
00249                     case ERASE_RELEASE:
00250                         assert(false);
00251                         break;
00252                     }
00253                 }
00254                 else
00255                 {
00256                     assert( false );
00257                 }
00258             }
00259 
00260     //-----------------------------------------------------------------
00261     // DATA *   GetData( HANDLE handle )
00262     //
00263     // dereferencing
00264     //-----------------------------------------------------------------
00265     DATA *  GetData( HANDLE handle )
00266             {
00267                 assert( !handle.IsNull() );
00268 
00269                 if ( handle.IsNull() )  return ( 0 );
00270 
00271                 unsigned int index = handle.GetIndex();
00272 
00273             #if _DEBUG
00274                 // check handle validity - $ this check can be removed for speed
00275                 // if you can assume all handle references are always valid.
00276                 if (   ( index >= m_UserData.size() )
00277                     || ( m_MagicNumbers[ index ] != handle.GetMagic() ) )
00278                 {
00279                     // no good! invalid handle == client programming error
00280                     return ( 0 );
00281                 }
00282             #endif
00283                 
00284                 return ( m_UserData.begin() + index );
00285             }
00286 
00287     //-----------------------------------------------------------------
00288     // const DATA * GetData( HANDLE handle ) const
00289     //
00290     // dereferencing
00291     //-----------------------------------------------------------------
00292     const DATA* GetData( HANDLE handle ) const
00293             {
00294                 // this lazy cast is ok - non-const version does not modify anything
00295                 return ( const_cast<THandleMgr<DATA, HANDLE>*> ( this )->GetData( handle ) );
00296             }
00297     
00298     //-----------------------------------------------------------------
00299     // EraseEntries(void)
00300     //-----------------------------------------------------------------
00301     void    EraseEntries(void)
00302             {
00303                 int i = 0;
00304                 int cnt = m_UserData.size();
00305 
00306                 assert( m_EraseType != ERASE_UNKNOWN );
00307 
00308                 switch( m_EraseType )
00309                 {
00310                 case ERASE_DELETE:
00311                     //for( i=0; i<cnt; i++ )
00312                     //  SAFE_DELETE(m_UserData[i]);
00313                     assert(false);
00314                     break;
00315 
00316                 case ERASE_DELETE_ARRAY:
00317                     //for( i=0; i<cnt; i++ )
00318                     //  SAFE_DELETE_ARRAY(m_UserData[i]);
00319                     assert(false);
00320                     break;
00321 
00322                 case ERASE_RELEASE:
00323                     //for( i=0; i<cnt; i++ )
00324                     //  SAFE_RELEASE(m_UserData[i]);
00325                     assert(false);
00326                     break;
00327                 }
00328 
00329                 m_UserData.clear();
00330                 m_MagicNumbers.clear();
00331                 m_FreeSlots.clear();
00332                 m_References.clear();
00333             }
00334     
00335     static THandleMgr<DATA, HANDLE> * GetHandleMgr(void) {  //assert(m_Singleton); 
00336                                                             return m_Singleton; }
00337 
00338 protected:
00339     // private data
00340     EraseType   m_EraseType;
00341     DataVec     m_UserData;     // data we're going to get to
00342     MagicVec    m_MagicNumbers; // corresponding magic numbers
00343     FreeVec     m_FreeSlots;    // keeps track of free slots in the db
00344     RefVec      m_References;
00345     
00346     static  THandleMgr<DATA, HANDLE> * m_Singleton;
00347 };
00348 
00349 
00350 //-----------------------------------------------------
00351 
00352 
00353 //--------------------------------------------------
00354 // THandle base
00355 //--------------------------------------------------
00356 template <typename TAG>
00357 class THandle
00358 {
00359 private:
00360     union
00361     {
00362         enum
00363         {
00364             // sizes to use for bit fields
00365             MAX_BITS_INDEX = 16,
00366             MAX_BITS_MAGIC = 16,
00367 
00368             // sizes to compare against for asserting dereferences
00369             MAX_INDEX = ( 1 << MAX_BITS_INDEX) - 1,
00370             MAX_MAGIC = ( 1 << MAX_BITS_MAGIC) - 1,
00371         };
00372 
00373         struct
00374         {
00375             unsigned m_Index : MAX_BITS_INDEX;  // index into resource array
00376             unsigned m_Magic : MAX_BITS_MAGIC;  // magic number to check
00377         };
00378         unsigned long m_Handle;
00379     };
00380 
00381     typedef THandleMgr< TAG, THandle<TAG> > ThisMgrType;
00382     typedef THandle<TAG>                    ThisType;
00383 
00384 public:
00385 
00386     THandle (void) : m_Handle( 0 ) {  }
00387     ~THandle(void)  
00388     { 
00389         m_Handle = 0;
00390     }
00391     //--------------------------------------------------
00392     // Init( U16 )
00393     //
00394     // Inits the handle with given index
00395     //--------------------------------------------------
00396     void    Init( unsigned int index )
00397             {
00398                 assert( IsNull() );             // don't allow reassignment
00399                 assert( index <= MAX_INDEX );   // verify range
00400 
00401                 static unsigned int s_AutoMagic = 0;
00402                 if ( ++s_AutoMagic > MAX_MAGIC )
00403                 {
00404                     s_AutoMagic = 1;    // 0 is used for "null handle"
00405                 }
00406 
00407                 m_Index = index;
00408                 m_Magic = s_AutoMagic;
00409             }
00410 
00411     unsigned int    GetIndex ( void ) const  { return (  m_Index  ); }
00412     unsigned int    GetMagic ( void ) const  { return (  m_Magic  ); }
00413     unsigned long   GetHandle( void ) const  { return (  m_Handle ); }
00414     TAG *           GetData  ( void ) const  { return (  (ThisMgrType::GetHandleMgr()->GetData( *this ))); }
00415     bool            IsNull   ( void ) const  { return ( !m_Handle ); }
00416     
00417     operator unsigned int ( void ) const  { return (  m_Handle );  }    
00418     
00419     THandle<TAG>& operator = ( const THandle<TAG>& r )
00420     {   
00421         m_Handle = r.m_Handle;
00422         return *this;
00423     }
00424 
00425     THandle<TAG>& operator = ( const DWORD& r )
00426     {   
00427         m_Handle = r;
00428         return *this;
00429     }
00430 
00431     
00432     friend bool operator != ( const THandle<TAG>& l, const THandle<TAG>& r )
00433                     {  return ( l.m_Handle != r.m_Handle );  }
00434 
00435     friend bool operator == ( const THandle<TAG>& l, const THandle<TAG>& r )
00436                     {  return ( l.m_Handle == r.m_Handle );  }
00437 
00438     friend bool operator != ( const DWORD& l, const THandle<TAG>& r )
00439                     {  return ( l != r.m_Handle );  }
00440 
00441     friend bool operator == ( const DWORD& l, const THandle<TAG>& r )
00442                     {  return ( l == r.m_Handle );  }
00443 
00444     friend bool operator != ( const THandle<TAG>& l, const DWORD& r )
00445                     {  return ( l.m_Handle != r );  }
00446 
00447     friend bool operator == ( const THandle<TAG>& l, const DWORD& r )
00448                     {  return ( l.m_Handle == r );  }
00449 };
00450 
00451 #endif

Generated on Mon Sep 12 19:58:56 2005 for Destiny3D by doxygen1.3-rc3